/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package dk.eleit.input;

import java.awt.Point;
import java.awt.event.*;

/**
 *
 * @author menderleit
 */
public final class InputManager implements KeyListener, MouseListener, MouseMotionListener {

    private boolean keyPressed;
    private boolean keyReleased;
    private long[] keys;
    private boolean[] keyDown;
    private boolean[] keyUp;
    private String keyCache;
    private static InputManager instance;
    private int mouseClick;
    private Point mousePoint;

    protected InputManager() {
        keyPressed = false;
        keyReleased = false;
        keys = new long[256];
        keyDown = new boolean[256];
        keyUp = new boolean[256];
        keyCache = "";
        mouseClick = 0;
        mousePoint = new Point(0,0);
    }

    public static InputManager getInstance() {
        if(instance == null){
            instance = new InputManager();
        }
        return instance;
    }

    @Override
    public void keyTyped(KeyEvent ke) {
        keyCache += ke.getKeyChar();
    }

    @Override
    public void keyPressed(KeyEvent ke) {
        if (ke.getKeyCode() >= 0 && ke.getKeyCode() < 256) {
            keys[ke.getKeyCode()] = System.nanoTime() / 1000000;
            keyDown[ke.getKeyCode()] = true;
            keyUp[ke.getKeyCode()] = false;
            keyPressed = true;
            keyReleased = false;
        }
    }

    @Override
    public void keyReleased(KeyEvent ke) {
        if (ke.getKeyCode() >= 0 && ke.getKeyCode() < 256) {
            keys[ke.getKeyCode()] = 0;
            keyDown[ke.getKeyCode()] = false;
            keyUp[ke.getKeyCode()] = true;
            keyPressed = false;
            keyReleased = true;
        }
    }

    // Returns TRUE if the key specified is pressed down.
    public boolean isKeyDown(int key) {
        return keyDown[key];
    }

    // Returns TRUE if the key specified is released.
    public boolean isKeyUp(int key) {
        return keyUp[key];
    }

    // Returns TRUE if any key was pressed down.
    public boolean isKeyPressed() {
        return keyPressed;
    }

    // Returns TRUE if any key was released.
    public boolean isKeyReleased() {
        return keyReleased;
    }

    // Updates the keyUp states so that a key doesn't report released more than once.
    // Also clears the keyCache when necessary.
    public void update() {
        keyUp = new boolean[256];
        keyReleased = false;
        if (keyCache.length() > 1024) {
            keyCache = "";
        }
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        mousePoint = e.getPoint();
    }

    @Override
    public void mousePressed(MouseEvent e) {
        mousePoint = e.getPoint();
        int mb = e.getButton();
        if(mb > 0) {
            mb -= 1;
            int bitMask = 1;
            bitMask = bitMask << mb;
            mouseClick = mouseClick | bitMask;
        }
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        mousePoint = e.getPoint();
        int mb = e.getButton();
        if (mb > 0) {
            mb -= 1;
            int bitMask = 1;
            bitMask = ~(bitMask << mb);
            mouseClick = mouseClick & bitMask;
        }
    }

    @Override
    public void mouseEntered(MouseEvent e) {
        mousePoint = e.getPoint();
    }

    @Override
    public void mouseExited(MouseEvent e) {
        mousePoint = e.getPoint();
    }

    @Override
    public void mouseDragged(MouseEvent e) {
        mousePoint = e.getPoint();
    }

    @Override
    public void mouseMoved(MouseEvent e) {
        mousePoint = e.getPoint();
    }
    
    public int getMouseClick() {
        return mouseClick;
    }
    
    public Point getMousePoint() {
        return mousePoint;
    }
    
    public boolean isLeftClick() {
        boolean click = false;
        if((mouseClick & MouseEvent.BUTTON1) == 1) {
            click = true;
        }
        return click;
    }
}
